
import { Vec2, log } from "cc";
import BaseInputMgr from "./BaseInputMgr";
import { HandleType, STEAM_DIR_LIST, STEAM_KEY_CODE, STEAM_KEY_LIST } from "./GamepadDefine";
import { IGamepadCtrl } from "./IGamepadCtrl";
import { InputType } from "./InputConfig";
import LocalValue from "../LocalValue";


const VEC_RIGHT = new Vec2(1, 0);
const vectorBuff = new Vec2();
/**
 * 手柄管理器
 */
export class BaseGamepadMgr extends BaseInputMgr {

    protected platName: string = InputType.STEAM;

    protected _gameCtrl: IGamepadCtrl;

    //存储摇杆触发的键值
    private joyStickPressState: boolean[] = []
    private analogStickPressKeyCodes: number[] = []
    //左右方向的摇杆是否将摇杆数值改为方向键值。
    private changeDirAnalog: boolean[] = [false, false]

    protected _handleType: HandleType = HandleType.XBOX;

    protected handleStorage: LocalValue = new LocalValue('SteamInputMgr', 0)
    init(actionSetNames: string[], digitalNames: string[], analogNames?: string[]) {
        this._handleType = this.handleStorage.getInt()
        log('this._handleType  ', this._handleType)
        this.initController();
        this.setChangeDirAnlog(0, true)
        this.setChangeDirAnlog(1, true)
        this.addCtrlModeListener()
        this.addKeyCode(STEAM_KEY_CODE)
    }

    setHandleType(type: HandleType) {
        this._handleType = type;
        this.handleStorage.setValue(type)
    }

    getHandleType() {
        return this._handleType;
    }

    protected initController() {
        // if (this.isActive()) {
        //     if (!this._gameCtrl) {
        //         this._gameCtrl = steam.SteamManager.getInstance();
        //         this._gameCtrl!.init(ACTION_SET, DIGITALS, ANALOGS);
        //         this._gameCtrl!.activeActionSet(ACTION_SET[0]);
        //         console.warn(' steam init ok ')
        //     }
        // } else {
        //     console.warn(' steam is error init ')
        // }
    }

    setChangeDirAnlog(index: number, flag: boolean) {
        this.changeDirAnalog[index] = flag;
    }

    protected _enable: boolean = false;

    isEnable() {
        return this._enable;
    }

    isActive() {
        return window['steam'] != undefined;
    }

    /**
     * 更新按键的状态
     * @param digital 
     * @param _joyStickPress 
     * @param _joyStickRelease 
     */
    private updateLogic(digital: number[], _joyStickPress: number[], _joyStickRelease: number[]) {

        if (digital.length <= 0) {
            return;
        }
        // console.log(' digital ', digital)
        for (let i = 0; i < digital.length; i += 2) {
            let keyCode = digital[i];
            // let keyValue = this.getKeyValue(keyCode)
            if (digital[i + 1]) {
                if (!this.joyStickPressState[keyCode]) {
                    this.joyStickPressState[keyCode] = true;
                    _joyStickPress.push(keyCode)
                    if (!this._active) {
                        this.changeType()
                    }
                }
            } else {
                if (this.joyStickPressState[keyCode]) {
                    this.joyStickPressState[keyCode] = false;
                    _joyStickRelease.push(keyCode)
                }
            }
        }
        // console.log(' this.joyStickPressState ', this.joyStickPressState)
        // console.log(' this._joyStickPress ', _joyStickPress)
        // console.log(' this._joyStickRelease ', _joyStickRelease)
    }

    update(deltaTime: number) {
        if (this._gameCtrl) {
            this._gameCtrl!.update();
            let _joyStickPress: number[] = [];
            let _joyStickRelease: number[] = [];
            let digital = this._gameCtrl!.getDigitalChangeData();
            let analog = this._gameCtrl!.getAnalogChangeData();
            this.updateLogic(digital, _joyStickPress, _joyStickRelease)
            if (analog.length > 0) {
                // console.log(' analog count ', analog.length, analog)
                for (let i = 0; i < analog.length; i += 3) {
                    let keyIndex = analog[i];
                    // console.log(' analog keyIndex ', keyIndex)
                    if (this.changeDirAnalog[i]) {
                        vectorBuff.set(analog[i + 1], analog[i + 2]);
                        //手指离开 已经使用摇杆
                        let tempAnalogPress: number[] = this.getDirKeyCode(vectorBuff)
                        this.updateLogic(tempAnalogPress, _joyStickPress, _joyStickRelease)
                    } else {
                        this.onRockerEvent(keyIndex, analog[i + 1], analog[i + 2])
                    }
                }
            } else {
                // this.updateDirKeyCode(_joyStickPress, _joyStickRelease)
            }

            if (_joyStickPress.length > 0) {
                this.changeType()
                for (let index = 0; index < _joyStickPress.length; index++) {
                    this.onKeyBoardPress(_joyStickPress[index])
                }
            }

            if (_joyStickRelease.length > 0) {
                for (let index = 0; index < _joyStickRelease.length; index++) {
                    this.onKeyBoardRelease(_joyStickRelease[index])
                }
            }
        }
    }

    /**
     * 键值是否包含指定按键
    */
    public isContainKeys(_keyCode: number, keys: number): boolean {
        return (_keyCode & keys) == keys;
    }


    private updateDirKeyCode(_joyStickPress: number[], _joyStickRelease: number[]) {
        for (let i = 0; i < STEAM_DIR_LIST.length; i++) {
            let keyCode = STEAM_DIR_LIST[i];
            // let keyValue = this.getKeyValue(keyCode)
            if (this.joyStickPressState[keyCode] && _joyStickPress.indexOf(keyCode) < 0) {
                _joyStickRelease.push(keyCode)
            }
        }
    }

    /**
     * 通过给定的向量，获得向量对应的方向键的键值
     * @param vectorBuff 
     * @returns 
     */
    private getDirKeyCode(vectorBuff: Vec2): number[] {
        let state: number[] = []
        // for (let index = 0; index < STEAM_DIR_LIST.length; index++) {
        //     const keyCode = STEAM_DIR_LIST[index];
        //     state[index * 2] = keyCode;
        //     state[index * 2 + 1] = 0;
        // }
        if (vectorBuff.length() > 0.9) {
            let angle = vectorBuff.angle(VEC_RIGHT) * 180 / Math.PI;
            if (vectorBuff.y < 0)
                angle = 360 - angle;
            // console.log('getDirKeyCode  angle ', angle, vectorBuff.x, vectorBuff.y)
            let section = 0;
            if (angle < 22.5)
                section = 7;
            else
                section = Math.floor((angle - 22.5) / 45);

            // console.log('getDirKeyCode  section ', section)
            let keyList = STEAM_KEY_LIST[section]
            if (keyList) {
                for (let index = 0; index < keyList.length; index++) {
                    const keyCode = keyList[index];
                    state.push(keyCode)
                    state.push(1)

                    // for (let j = 0; j < state.length; j += 2) {
                    //     if (state[j] == keyCode) {
                    //         state[j + 1] = 1
                    //         break;
                    //     }
                    // }
                }

                // console.log('getDirKeyCode  state ', state)
            }

        }
        let deleteKey: number[] = []
        for (let index = 0; index < this.analogStickPressKeyCodes.length; index++) {
            const oldKey = this.analogStickPressKeyCodes[index];
            let has: boolean = false;
            for (let j = 0; j < state.length; j += 2) {
                const newKey = state[j];
                if (oldKey == newKey) {
                    has = true;
                    break;
                }
            }
            if (!has) {
                deleteKey.push(oldKey)
            }
        }
        for (let index = 0; index < deleteKey.length; index++) {
            const keyCode = deleteKey[index];
            state.push(keyCode)
            state.push(0)
            let idx = this.analogStickPressKeyCodes.indexOf(keyCode)
            if (idx >= 0) {
                this.analogStickPressKeyCodes.splice(idx, 1)
            }
        }
        for (let j = 0; j < state.length; j += 2) {
            const newKey = state[j];
            let idx = this.analogStickPressKeyCodes.indexOf(newKey)
            if (idx < 0) {
                this.analogStickPressKeyCodes.push(newKey)
            }
        }
        return state;
    }
}